package bean.managed;

import entity.RawMaterialRequirementWeeklyEntity;
import bean.managed.util.JsfUtil;
import bean.managed.util.PaginationHelper;
import bean.session.RawMaterialEntityFacade;
import bean.session.RawMaterialRequirementWeeklyEntityFacade;

import entity.RawMaterialEntity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;
import managedbean.AbstractBacking;
import org.primefaces.model.DualListModel;
import type.Month;


@ManagedBean(name = "rawMaterialRequirementWeeklyEntityController")
@SessionScoped
public class RawMaterialRequirementWeeklyEntityController extends AbstractBacking implements Serializable {

    private RawMaterialRequirementWeeklyEntity current;
    private RawMaterialRequirementWeeklyEntity recievingWeek;// for dialog.show();
    private long previousMonthOnHand; // for mrp table
    private DataModel items = null;
    private int yearOfMrp;
    private Month monthOfMrp;
    List<RawMaterialRequirementWeeklyEntity> allMRPsByMonth=new ArrayList<RawMaterialRequirementWeeklyEntity>();
    List<RawMaterialRequirementWeeklyEntity> mrpsInThisMonth; // list according to raw material name
    List<RawMaterialRequirementWeeklyEntity> mrpsThisMonthForThisRawMaterial;
    
    @EJB
    private bean.session.RawMaterialRequirementWeeklyEntityFacade ejbFacade;
    @EJB
    private bean.session.RawMaterialEntityFacade rmfacade;

    
    private PaginationHelper pagination;
    private int selectedItemIndex;
    
    

    public RawMaterialRequirementWeeklyEntityController() {
    }
    
    public String deleteMrpMonth(RawMaterialRequirementWeeklyEntity mrp){
        int year = mrp.getYearOfProduction();
        Month month = mrp.getMonthOfProduction();
        List<RawMaterialRequirementWeeklyEntity> list = getFacade().searchAllMRPsInThisMonth(year, month);
//        System.out.println("Year is "+ year);
//        System.out.println("Month is "+ month);
//        System.out.println("deleteList.size() "+list.size());
        for(RawMaterialRequirementWeeklyEntity r: list){
         
           getFacade().remove(r);
           
       }
        return prepareList();
    
    }
    
    public RawMaterialRequirementWeeklyEntity getCurrent() {
        return current;
    }

    public void setCurrent(RawMaterialRequirementWeeklyEntity current) {
        this.current = current;
    }
    
    public List<RawMaterialRequirementWeeklyEntity> getAllMRPsByMonth() {
       List<RawMaterialRequirementWeeklyEntity> allMRPs = ejbFacade.findAll();
       allMRPsByMonth=new ArrayList<RawMaterialRequirementWeeklyEntity>();
       for(RawMaterialRequirementWeeklyEntity week : allMRPs){
           boolean addMRP = true;
           if(allMRPsByMonth.size()==0){
               
           }
           else{
               for(RawMaterialRequirementWeeklyEntity r : allMRPsByMonth){
                   if(r.getYearOfProduction()==week.getYearOfProduction()&&r.getMonthOfProduction()==week.getMonthOfProduction()){
                       addMRP = false;
                   }
               }
           }
           if(addMRP==true){
               allMRPsByMonth.add(week);
           }
       }
       
        return allMRPsByMonth;
    }
    
    public void setRecievingWeek(RawMaterialRequirementWeeklyEntity r){
        recievingWeek = r;
    }
    
    public RawMaterialRequirementWeeklyEntity getRecievingWeek(){
        recievingWeek = new RawMaterialRequirementWeeklyEntity();
        int currentWeekNum = current.getWeekOfProduction();
        Month currentMonth = current.getMonthOfProduction();
        int currentYear = current.getYearOfProduction();
        int leadTime = current.getRawMaterial().getLeadTime();
        recievingWeek.setRawMaterial(current.getRawMaterial());
        
        System.out.println("currentYear "+currentYear);
        System.out.println("currentMonth "+currentMonth);
        System.out.println("currentYear "+currentWeekNum);
        
        int currentMonthTotalWeeks = mrpsThisMonthForThisRawMaterial.size();
        
        if(currentWeekNum+leadTime<= currentMonthTotalWeeks){
            recievingWeek = mrpsThisMonthForThisRawMaterial.get(currentWeekNum+leadTime-1);
        }
        else if(currentMonth==Month.DECEMBER){
            recievingWeek.setYearOfProduction(currentYear+1);
            recievingWeek.setMonthOfProduction(Month.JANUARY);
            recievingWeek.setWeekOfProduction(currentWeekNum+leadTime-currentMonthTotalWeeks);
            recievingWeek.setGrossRequirement(getFacade().findGrossRequirementForUncreatedMRP(recievingWeek));
        }
        else{
            recievingWeek.setYearOfProduction(currentYear);
            recievingWeek.setMonthOfProduction(Month.fromMonthNum(currentMonth.getMonthNum()+1));
            recievingWeek.setWeekOfProduction(currentWeekNum+leadTime-currentMonthTotalWeeks);
            recievingWeek.setGrossRequirement(getFacade().findGrossRequirementForUncreatedMRP(recievingWeek));
        }
            
        
        
        return recievingWeek;
    }
    
    public void setPreviousMonthOnHand(long previous){
        previousMonthOnHand = previous;
    }
    
    public long getPreviousMonthOnHand(){
        return previousMonthOnHand;
    }
    
     public void validatePlannedOrder(FacesContext context, UIComponent validate, Object value) {

        long planOrder = (Long) value;
        int lotSize = current.getRawMaterial().getLotSize();
        if (planOrder<0) {
            FacesMessage message = new FacesMessage();
            message.setDetail("Plan orders must not be negative number !");
            message.setSummary("Plan orders must not be negative number !");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(message);
        }
        if (planOrder%lotSize!=0) {
            FacesMessage message = new FacesMessage();
            message.setDetail("Plan orders must be multiple of lot size !");
            message.setSummary("Plan orders must be multiple of lot size !");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(message);
        }
        
    }
    
    
    
    public  void setAllMRPsByMonth(List<RawMaterialRequirementWeeklyEntity> list) {
        allMRPsByMonth = list;
   
    }
    
  
    
    public void updateMRPs(){
        RawMaterialEntity material = mrpsThisMonthForThisRawMaterial.get(0).getRawMaterial();
        int leadTime = material.getLeadTime();
        
        System.out.println("doing update");
        for(RawMaterialRequirementWeeklyEntity mrp: mrpsThisMonthForThisRawMaterial){
            mrp.setPlannedReceipt(getFacade().findPlannedOrder(mrp));
            mrp.setOnHandQuantity(getFacade().calculateOnHand(mrp));
            getFacade().edit(mrp);
        }
    }
    
    
    public DualListModel<String> getRmsPickList() {

        List<RawMaterialEntity> allRMEntityList = new ArrayList<RawMaterialEntity>();

       allRMs.clear();
        allRMEntityList = rmfacade.findAllIncludeArchived();

        for (int i = 0; i < allRMEntityList.size(); i++) {

            allRMs.add(allRMEntityList.get(i).getProductName());

        }

        rmsPickList = new DualListModel<String>(allRMs, choosenRMs);

        return rmsPickList;

    }
//for picklist
    List<String> allRMs = new ArrayList<String>();
    List<String> choosenRMs = new ArrayList<String>();
    private DualListModel<String> rmsPickList;

    public List<String> getAllRMs() {
        return allRMs;
    }

    public void setAllRMs(List<String> allRMs) {
        this.allRMs = allRMs;
    }

    public List<String> getChoosenRMs() {
        return rmsPickList.getTarget();
    }

    public void setChoosenRMs(List<String> choosenRMs) {
        this.choosenRMs = choosenRMs;
    }

    public void setRmsPickList(DualListModel<String> rmsPickList) {
        this.rmsPickList = rmsPickList;
    }
    
    public RawMaterialEntityFacade getrmFacade() {
        return rmfacade;
    }


    public RawMaterialRequirementWeeklyEntity getSelected() {
        if (current == null) {
            current = new RawMaterialRequirementWeeklyEntity();
            selectedItemIndex = -1;
        }
        return current;
    }

    private RawMaterialRequirementWeeklyEntityFacade getFacade() {
        return ejbFacade;
    }
    
    private void setYearOfMrp(int year){
       yearOfMrp = year;
    }
    
    private int getYearOfMrp(){
        return yearOfMrp;
    }
    
    private void setMonthOfMrp(Month month){
        monthOfMrp = month;
    }
    
    
    private Month getMonthOfMrp(){
        return monthOfMrp;
    }
    
    
    
    public Month[] getAllMrpMonth() {
        return Month.values();
    }

    public PaginationHelper getPagination() {
        if (pagination == null) {
            pagination = new PaginationHelper(10) {

                @Override
                public int getItemsCount() {
                    return getFacade().count();
                }

                @Override
                public DataModel createPageDataModel() {
                    return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
                }
            };
        }
        return pagination;
    }

    public String prepareList() {
        recreateModel();
        return "/entities/rawMaterialRequirementWeeklyEntity/List?faces-redirect=true";
    }

    public String prepareView() {
        current = (RawMaterialRequirementWeeklyEntity) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "View";
    }
    
    public String listMrpsThisMonth(RawMaterialRequirementWeeklyEntity week){
        current = week;
        mrpsInThisMonth = new ArrayList<RawMaterialRequirementWeeklyEntity>();
        Month month = week.getMonthOfProduction();
        int year = week.getYearOfProduction();
//        RawMaterialEntity material = week.getRawMaterial();
//        mrpsInThisMonth = getFacade().searchMRPsInThisMonth(year,month,material);
        mrpsInThisMonth = getFacade().searchMRPsInThisMonth(year,month);
        return "/entities/rawMaterialRequirementWeeklyEntity/ListMrpsThisMonth?faces-redirect=true";
        
    }
    
    public String listMrpsThisMonthForThisMaterial(RawMaterialRequirementWeeklyEntity week){
        current = week;
        mrpsThisMonthForThisRawMaterial = new ArrayList<RawMaterialRequirementWeeklyEntity>();
        Month month = week.getMonthOfProduction();
        int year = week.getYearOfProduction();
        RawMaterialEntity material = week.getRawMaterial();
        mrpsThisMonthForThisRawMaterial = getFacade().searchMRPsInThisMonthForThisMaterial(year,month,material);
        previousMonthOnHand = getFacade().findPreviousMonthOnHand(mrpsThisMonthForThisRawMaterial.get(0));
//        mrpsInThisMonth = getFacade().searchMRPsInThisMonth(year,month);
        return "/entities/rawMaterialRequirementWeeklyEntity/ListMrpsThisMonthForThisRawMaterial?faces-redirect=true";
        
    }
    
    
    public List<RawMaterialRequirementWeeklyEntity> getMrpsThisMonthForThisRawMaterial (){
        return mrpsThisMonthForThisRawMaterial;
    }
    
    public void setMrpsThisMonthForThisRawMaterial(List<RawMaterialRequirementWeeklyEntity> list){
        mrpsThisMonthForThisRawMaterial = list;
    }
    
    public List<RawMaterialRequirementWeeklyEntity> getAllMrpsInThisMonth (){
        return mrpsInThisMonth;
    }
    
    public void setAllMrpsInThisMonth(List<RawMaterialRequirementWeeklyEntity> list){
        mrpsInThisMonth = list;
    }

    public String prepareCreate() {
//        current = new RawMaterialRequirementWeeklyEntity();
//        selectedItemIndex = -1;
        recreateModel();
        return "/entities/rawMaterialRequirementWeeklyEntity/Create?faces-redirect=true";
    }

    public String create() {
        try {
            
           if (ejbFacade.checkExistence(current.getYearOfProduction(),current.getMonthOfProduction())) {
//            System.out.println("Should Print error message");
            FacesMessage message = new FacesMessage();
            message.setDetail("Mrp exists");
            message.setSummary("Mrp exists");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
//            String msg = "Sales Forecast exists";
//            throw new ValidatorException(new FacesMessage(msg));
            throw new ValidatorException(message);
        }
//            List<String> choosenRMs = rmsPickList.getTarget();
            Collection<RawMaterialEntity> rmss = getrmFacade().findAllRMs();
//             for (String rm : choosenRMs) {
//            RawMaterialEntity r = getrmFacade().findRawMaterial(rm);
//            rmss.add(r);
        
            getFacade().createMonthlyMRP(current,rmss,getLoginPerson());
           
            JsfUtil.addSuccessMessage("Material Requirement Plans Created");
            String address = listMrpsThisMonth(current);
          
            return address;
//            return prepareCreate();
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            System.out.println("not created");
            return null;
        }
    }

   
    
    public String prepareEdit() {
        current = (RawMaterialRequirementWeeklyEntity) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "Edit";
    }

    public String update() {
        try {
            getFacade().edit(current);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("RawMaterialRequirementWeeklyEntityUpdated"));
            return "View";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }

    public String destroy() {
        current = (RawMaterialRequirementWeeklyEntity) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        performDestroy();
        recreateModel();
        return "List";
    }

    public String destroyAndView() {
        performDestroy();
        recreateModel();
        updateCurrentItem();
        if (selectedItemIndex >= 0) {
            return "View";
        } else {
            // all items were removed - go back to list
            recreateModel();
            return "List";
        }
    }

    private void performDestroy() {
        try {
            getFacade().remove(current);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("RawMaterialRequirementWeeklyEntityDeleted"));
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
        }
    }

    private void updateCurrentItem() {
        int count = getFacade().count();
        if (selectedItemIndex >= count) {
            // selected index cannot be bigger than number of items:
            selectedItemIndex = count - 1;
            // go to previous page if last page disappeared:
            if (pagination.getPageFirstItem() >= count) {
                pagination.previousPage();
            }
        }
        if (selectedItemIndex >= 0) {
            current = getFacade().findRange(new int[]{selectedItemIndex, selectedItemIndex + 1}).get(0);
        }
    }

    public DataModel getItems() {
        if (items == null) {
            items = getPagination().createPageDataModel();
        }
        return items;
    }

    private void recreateModel() {
        items = null;
        current = null;
         
    }

    public String next() {
        getPagination().nextPage();
        recreateModel();
        return "List";
    }

    public String previous() {
        getPagination().previousPage();
        recreateModel();
        return "List";
    }

    public SelectItem[] getItemsAvailableSelectMany() {
        return JsfUtil.getSelectItems(ejbFacade.findAll(), false);
    }

    public SelectItem[] getItemsAvailableSelectOne() {
        return JsfUtil.getSelectItems(ejbFacade.findAll(), true);
    }

    @FacesConverter(forClass = RawMaterialRequirementWeeklyEntity.class)
    public static class RawMaterialRequirementWeeklyEntityControllerConverter implements Converter {

        public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
            if (value == null || value.length() == 0) {
                return null;
            }
            RawMaterialRequirementWeeklyEntityController controller = (RawMaterialRequirementWeeklyEntityController) facesContext.getApplication().getELResolver().
                    getValue(facesContext.getELContext(), null, "rawMaterialRequirementWeeklyEntityController");
            return controller.ejbFacade.find(getKey(value));
        }

        java.lang.Long getKey(String value) {
            java.lang.Long key;
            key = Long.valueOf(value);
            return key;
        }

        String getStringKey(java.lang.Long value) {
            StringBuffer sb = new StringBuffer();
            sb.append(value);
            return sb.toString();
        }

        public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
            if (object == null) {
                return null;
            }
            if (object instanceof RawMaterialRequirementWeeklyEntity) {
                RawMaterialRequirementWeeklyEntity o = (RawMaterialRequirementWeeklyEntity) object;
                return getStringKey(o.getId());
            } else {
                throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + RawMaterialRequirementWeeklyEntityController.class.getName());
            }
        }
    }
}
